#!/user/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Ljx
Description: 载荷计算
需要引入 pip install matplotlib
信号：
save_data_signal(dict)  确认按钮  全部表单数据 create_item={"lifeStatisticsResults":string,"optimizationAlgorithms":string,
use_data_signal(dict)  同上                               "optimizeTheNether":float,"optimizeTheTpper":float,"terminationError":float,
                                                            "maxCirculate":int,"inversionResults":string}
start_operation(dict)  运算按钮  全部表单数据
show_operation(dict)  点击显示按钮的信号  全部表单数据
update_plot(echarts_data:dict={},value,update_inversionResults)  更新折线统计图  echarts_data={"xFontLabel":"X轴文字","yFontLabel":"Y轴文字","x":[1,2,3,4],"y":[0.1,0.2,0.3,0.4]},
                                                        value=string 寿命统计结果的值 update_inversionResults  更新反演结果的值
"""

__all__ = []
import sys
from PyQt5.QtWidgets import (
    QHBoxLayout,
    QPushButton,
    QApplication,
    QVBoxLayout,
    QWidget,
    QComboBox,
    QLineEdit,
    QFileDialog,
    QDialog,
    QLabel,
)
from PyQt5.QtCore import QRegExp
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtGui import QDoubleValidator, QIntValidator
from PyQt5.QtCore import pyqtSignal
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

global parameter
parameter = []


class LoadCalculations(QDialog):
    # 确认按钮
    save_data_signal = pyqtSignal(dict)
    use_data_signal = pyqtSignal(dict)
    start_operation = pyqtSignal(dict)
    show_operation = pyqtSignal(dict)

    def __new__(
        cls,
        args,
        optimizationAlgorithmsList: list = [],
        echarts_data: dict = {},
        **kwargs,
    ):
        isAdd = True
        global parameter
        if len(parameter) > 0:
            for item in parameter:
                #   有相同的 就直接关闭吧
                if item == args:
                    isAdd = False
                    return None
        if isAdd:
            parameter.append(args)
        return super().__new__(cls)

    def __init__(
        self,
        create_item: dict = {},
        optimizationAlgorithmsList: list = [],
        echarts_data: dict = {},
        parent=None,
    ):
        super().__init__(parent)
        self.create_item = create_item
        self.echarts_data = echarts_data
        self.optimizationAlgorithmsList = optimizationAlgorithmsList
        # 图标显示数据
        self.initUI()

    def use_click(self):
        self.use_data_signal.emit(self.get_data())

    def save_click(self):
        data = self.get_data()
        self.closeDialog()
        self.save_data_signal.emit(data)

    def closeDialog(self):
        global parameter
        for item in parameter:
            #   有相同的 就直接关闭吧
            if item == self.create_item:
                parameter.remove(item)
                break
        self.deleteLater()
        self.close()

    def update_plot(
        self, echarts_data: dict = {}, value="", update_inversionResults=""
    ):
        isContinue = False
        global parameter
        for item in parameter:
            #   如果还存在 name继续赋值
            if item == self.create_item:
                isContinue = True
                break
        # 如果还存在那么继续赋值 如果不存在了 取消赋值
        print("value=", value)
        if isContinue:
            if value:
                self.line_edits[0].setText(value)
            if update_inversionResults:
                self.line_edits[6].setText(update_inversionResults)
            # echarts_data 为空的时候不更新图表
            if echarts_data:
                """更新折线图"""
                # 生成随机数据（示例）
                x = echarts_data.get("x", [])
                y = echarts_data.get("y", [])
                # 清除旧图表
                self.figure.clear()
                ax = self.figure.add_subplot(111)
                # 设置字体 很重要
                plt.rcParams["font.sans-serif"] = ["SimHei"]
                plt.rcParams["axes.unicode_minus"] = False
                # 绘制新折线图
                ax.plot(
                    x, y, marker="o", linestyle="-", color="#3498db", label="迭代曲线"
                )
                ax.set_title(f"迭代曲线", pad=14)
                ax.set_xlabel(f"{echarts_data.get('xFontLabel','x')}")
                ax.set_ylabel(f"{echarts_data.get('yFontLabel','y')}")
                ax.grid(True, linestyle="--", alpha=1)
                ax.legend()
                # 刷新画布
                self.canvas.draw()
            else:
                pass

    # 获取数据
    def get_data(self):
        # 获取表格中所有的数据
        dataForm = {}
        for row, (prop, value, field_type, key, default_value, readonly) in enumerate(
            self.data
        ):
            if field_type == "combo":
                dataForm[key] = self.line_edits[row].currentData()
            else:
                if field_type == "number" and key == "maxCirculate":
                    dataForm[key] = (
                        int(self.line_edits[row].text())
                        if self.line_edits[row].text()
                        else 0
                    )
                elif field_type == "number":
                    dataForm[key] = (
                        float(self.line_edits[row].text())
                        if self.line_edits[row].text()
                        else 0.0
                    )

                else:
                    dataForm[key] = self.line_edits[row].text()
        return dataForm

    def initUI(self):
        self.rejected.connect(self.closeDialog)
        self.setWindowTitle("载荷计算")
        self.resize(1200, 500)
        layout = QVBoxLayout()
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(0)
        # 示例数据 (属性名, 提示文本, 值的类型,键名,默认值)
        self.data = [
            ("寿命统计结果", "", "text", "lifeStatisticsResults", "", True),
            ("选择优化算法", "", "combo", "optimizationAlgorithms", "", False),
            ("优化下界", "", "number", "optimizeTheNether", "1", False),
            ("优化上界", "", "number", "optimizeTheTpper", "100", False),
            ("终止误差", "", "number", "terminationError", "1", False),
            ("最大循环次数", "", "number", "maxCirculate", "20", False),
            ("反演结果", "", "textBtn", "inversionResults", "", False),
        ]
        # 按照属性名分组
        self.combo_options = {
            "选择优化算法": self.optimizationAlgorithmsList,
        }
        self.line_edits = []

        # 给表格中的文本框赋值
        def set_first_row_text(row, text):
            if self.line_edits:
                self.line_edits[row].setText(str(text))

        # 上传文件地址
        def on_button_click(r):
            fname = QFileDialog.getOpenFileName(self, "选择文件", "", "")
            if fname[0]:
                set_first_row_text(r, fname[0])

        # 填充数据并设置控件
        allWidgets = QWidget()
        allWidgets_layout = QHBoxLayout(allWidgets)
        allWidgets_layout.setContentsMargins(0, 0, 0, 0)
        fromWidgets = QWidget()
        fromWidgets.setObjectName("parentContainer1")
        fromWidgets_layout = QVBoxLayout(fromWidgets)
        fromWidgets_layout.setContentsMargins(0, 0, 0, 0)
        fromWidgets_layout.setSpacing(0)
        for row, (prop, value, field_type, key, default_value, readonly) in enumerate(
            self.data
        ):
            fromWidgetX = QWidget()
            fromWidgetX_layout = QHBoxLayout(fromWidgetX)
            fromWidgetX_layout.setContentsMargins(0, 0, 0, 0)
            fromWidgetX_layout.setSpacing(0)
            # 放左侧文本
            label_widget = QWidget()
            label_layout = QHBoxLayout(label_widget)
            prop_label = QLabel(prop)
            prop_label.setFixedWidth(100)
            label_layout.addWidget(prop_label)
            fromWidgetX_layout.addWidget(label_widget)
            page = QWidget()
            page_layout = QHBoxLayout(page)
            page_layout.setContentsMargins(10, 0, 10, 0)
            # 下拉框
            if field_type == "combo":
                combo = QComboBox()
                for item in self.combo_options.get(prop, []):
                    combo.addItem(item.get("title"), item.get("value"))
                for item in self.combo_options.get(prop, []):
                    if item.get("value") == self.create_item.get(key, ""):
                        combo.setCurrentText(item.get("title"))
                page_layout.addWidget(combo)
                fromWidgetX_layout.addWidget(page, 1)
                self.line_edits.append(combo)
            # 上传文件地址
            elif field_type == "textBtn":
                line_edit = QLineEdit()
                line_edit.setClearButtonEnabled(True)
                line_edit.setPlaceholderText(str(value))
                line_edit.setText(self.create_item.get(key, ""))
                buttom1 = QPushButton("...")
                buttom1.clicked.connect(lambda _, r=row: on_button_click(r))
                buttom2 = QPushButton("显示按钮")
                buttom2.clicked.connect(
                    lambda: self.show_operation.emit(self.get_data())
                )
                buttom3 = QPushButton("开始运算")
                buttom3.clicked.connect(
                    lambda: self.start_operation.emit(self.get_data())
                )
                self.line_edits.append(line_edit)
                page_layout.addWidget(line_edit)
                # page_layout.addWidget(buttom1)
                # page_layout.addWidget(buttom2)
                page_layout.addWidget(buttom3)
                fromWidgetX_layout.addWidget(page, 1)
            # 文本
            else:
                value_item = QLineEdit()
                value_item.setReadOnly(readonly)
                value_item.setText(
                    str(
                        self.create_item.get(key, "")
                        if self.create_item.get(key, "")
                        else default_value
                    )
                )
                value_item.setClearButtonEnabled(True)
                if field_type == "number":
                    if key == "maxCirculate":
                        validator = QIntValidator(
                            1, 2147483647
                        )  # 最小=1，最大=INT_MAX (避免小数和负数)
                        value_item.setValidator(validator)
                    elif key != "maxCirculate":
                        validator = QDoubleValidator()
                        validator.setNotation(QDoubleValidator.StandardNotation)
                        value_item.setValidator(validator)
                    else:
                        #  正则限制输入范围
                        regex = QRegExp(r"^(0(\.\d{0,5})?|1(\.0{0,5})?)$")
                        regex_validator = QRegExpValidator(regex)
                        value_item.setValidator(regex_validator)
                page_layout.addWidget(value_item)
                self.line_edits.append(value_item)
                fromWidgetX_layout.addWidget(page)
            fromWidgets_layout.addWidget(fromWidgetX)
        self.bottomBtn = QWidget()
        self.usetBtn = QPushButton("应用")
        # self.usetBtn.setFixedSize(100,20)
        self.usetBtn.clicked.connect(self.use_click)
        self.savetBtn = QPushButton("应用并退出")
        # self.savetBtn.setFixedSize(100,20)
        self.savetBtn.clicked.connect(self.save_click)
        self.cancelBtn = QPushButton("关闭")
        # self.cancelBtn.setFixedSize(100,20)
        self.cancelBtn.clicked.connect(self.closeDialog)
        self.bottomBtn_layout = QHBoxLayout(self.bottomBtn)  # 创建布局
        self.bottomBtn_layout.addStretch(1)
        self.bottomBtn_layout.addWidget(self.usetBtn)
        self.bottomBtn_layout.addWidget(self.savetBtn)
        self.bottomBtn_layout.addWidget(self.cancelBtn)
        self.bottomBtn_layout.addStretch(1)
        # 图表画布
        self.figure = Figure(figsize=(6, 4), dpi=100)
        self.canvas = FigureCanvas(self.figure)
        # 初始化图表
        self.update_plot(self.echarts_data)
        allWidgets_layout.addWidget(fromWidgets, 1)
        allWidgets_layout.addWidget(self.canvas, 1)
        layout.addWidget(allWidgets, 1)
        layout.addWidget(self.bottomBtn)
        self.setLayout(layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    # 初始化数据
    create_item = {"lifeStatisticsResults": "1"}
    # 下拉框的list
    optimizationAlgorithmsList = [
        {"title": "二分法", "value": "1"},
        {"title": "牛顿法", "value": "2"},
    ]
    # 图标的数据
    echarts_data = {"xFontLabel": "", "yFontLabel": "", "x": [], "y": []}
    LoadCalculations = LoadCalculations(
        create_item, optimizationAlgorithmsList, echarts_data
    )
    LoadCalculations.setMinimumSize(1000, 400)
    LoadCalculations.show()
    sys.exit(app.exec_())
